#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date    : 2014-06-22 00:38:47
# @Author  : shitao.tommy (hero007asd@gmail.com)
# @Link    : http://example.org
# @Version : $Id$

import pickle
import hmac
import uuid
import hashlib
import time
import logging
import libtime

class CommonSessionStore():
    '''common session backend in memory
    '''
    def __init__(self, **options):
        self.options = {
            'key_prefix': 'session',
            'expire': 7200,
            }
        self.options.update(options)
        self.conn = {}

    def prefixed(self, sid):
        return '%s:%s' % (self.options['key_prefix'], sid)

    def generate_sid(self):
        return uuid.uuid4().get_hex()

    def _generate_id(self):
        new_id = hashlib.sha256(self.secret + str(uuid.uuid4()))
        return new_id.hexdigest()

    def _generate_hmac(self, session_id):
        return hmac.new(session_id, self.secret, hashlib.sha256).hexdigest()

    def get_session(self, sid, name):
        data = self.conn.get(self.prefixed(sid))
        session = pickle.loads(data) if data else {}
        return session

    def set_session(self, sid, session_data, name, expiry=None):
        expiry = expiry or self.options['expire']
        if expiry:
            self.conn[self.prefixed(sid)] = pickle.dumps(session_data)

    def delete_session(self, sid):
        if self.prefixed(sid) in self.conn:
            del self.conn[self.prefixed(sid)]

#TODO
# from vendor.redis.base import init_redis
from vendor.redis.tredis import Tredis
class RedisSessionStore(CommonSessionStore):
    '''store session in redis
    '''
    def __init__(self, **options):
        self.options = {
            'key_prefix': 'session',
            'expire': 7200,
            }
        self.options.update(options)
        # TODO 连接子
        self.conn = Tredis()

    def get_session(self, sid, name):
        # data = self.conn.get(self.prefixed(sid))
        data = self.conn.hm_select(self.prefixed(sid),name)
        return data[0]
        # session = pickle.loads(data[0]) if data[0] else {}
        # return session

    def set_session(self, sid, session_data, name, expiry=None):
        self.conn.hm_insert(self.prefixed(sid), session_data)
        self.conn.expire(self.prefixed(sid), expiry)

        # expiry = expiry or self.options['expire']
        # if expiry:
        #     self.conn.set(self.prefixed(sid), pickle.dumps(session_data), expiry)
    def delete_session(self, sid):
        self.conn.delete(self.prefixed(sid))

class Session:

    def __init__(self, session_store, session_id=None, expires_days=None):
        self._store = session_store
        self._sid = session_id if session_id else self._store.generate_sid()
        self._dirty = False
        self.set_expires(expires_days)
        try:
            self._data = self._store.get_session(self._sid, 'user')
        except Exception,ex:
            logging.error(ex)
            self._data = {}

    def clear(self):
        self._store.delete_session(self._sid)

    @property
    def id(self):
        return self._sid

    def access(self, remote_ip):
        access_info = {'remote_ip': remote_ip, 'time:':libtime.get_local_datetime()}
        self._store.set_session(
            self._sid,
            'last_access',
            pickle.dumps(access_info)
        )

    def last_access(self):
        access_info = self._store.get_session(self._sid, 'last_access')
        return pickle.loads(access_info)

    def set_expires(self, days):
        self._expires = days * 86400 if days else None

    def __getitem__(self, key):
        return self._store.get_session(self._sid, key)
        # return self._data[key]

    def __setitem__(self, key, value):
        self._store.set_session(self._sid,{key:value},'',24*60*60)
        # self._data[key] = value
        # self._dirty = True
        # self.save()

    def __delitem__(self, key):
        self._store.delete_session(self._sid)
        # del self._data[key]
        self._dirty = True

    def __len__(self):
        return len(self._data)

    def __contains__(self, key):
        return key in self._data

    def __iter__(self):
        for key in self._data:
            yield key

    def __repr__(self):
        return self._data.__repr__()

    # def __del__(self):
    #     self.save()

    # def save(self):
    #     if self._dirty:
    #         self._store.set_session(self._sid, self._data, 'data', self._expires)
    #         self._dirty = False
    
